const parse = require('@babel/parser').parse;
const generator = require('@babel/generator').default;
const traverse = require('@babel/traverse').default;
const fs = require('fs');
const path = require('path');
const {
  getAst,
  getFileContent,
  getFileDefinationAstMap,
  getModuleOrPathMap,
  getAbsolutePath,
  looksLike,
} = require('./util');

function entryWalk() {
  const base = path.resolve(__dirname, '../src/store/index.js');
  let entryFile = getFileContent(base);
  let entryAst = getAst(entryFile);
  let entryDefineAstMap = getFileDefinationAstMap(entryAst);
  let entryModuleOrPathMap = getModuleOrPathMap(entryAst);
  let config;
  traverse(entryAst, {
    NewExpression(path) {
      let isVuexCallLike = looksLike(path, {
        node: {
          callee: {
            type: 'MemberExpression',
            object: {
              name: 'Vuex',
            },
            property: {
              name: 'Store',
            },
          },
        },
      });
      if (isVuexCallLike) {
        let node = path.node;
        config = node.arguments[0];
      }
    },
  });
  let storeInfo = parseModuleAst({
    objAst: config,
    m2pmap: entryModuleOrPathMap,
    defmap: entryDefineAstMap,
    cwf: base,
    lineOfFile: entryFile.split('\n'),
  });
  console.log(storeInfo);
}

function parseModuleAst({ objAst, m2pmap, defmap, cwf, lineOfFile }) {
  let infoObj = {};
  objAst.properties.forEach(property => {
    let value = property.value;
    switch (property.key.name) {
      case 'state':
        if (property.shorthand) {
          if (m2pmap[value.name]) {
            let { export: importState, lineOfFile } = walkFile(
              cwf,
              m2pmap[value.name],
            );
            infoObj.state = parseState(importState, lineOfFile);
          } else if (defmap[value.name]) {
            infoObj.state = parseState(defmap[value.name], lineOfFile);
          }
        } else {
          infoObj.state = parseState(value, lineOfFile);
        }
        break;
      case 'actions':
        parseActions(property.value, m2map, defmap);
        break;
      case 'getters':
        parseGetters(property.value, m2pmap, defmap);
        break;
      case 'mutations':
        parseMutations(property.value, m2map, defmap);
        break;
      case 'modules':
        if (property.shorthand) {
          if (m2pmap[value.name]) {
            let {
              cwf: cwff,
              m2pmap: m2pmapp,
              objAst: objAstt,
              defmap: defmapp,
              lineOfFile: lineOfFilee,
            } = walkModulesFile(cwf, m2pmap[value.name]);
            infoObj.modules = parseModules({
              objAst: objAstt,
              m2pmap: m2pmapp,
              defmap: defmapp,
              cwf: cwff,
              lineOfFIle: lineOfFilee,
            });
          } else if (defmap[value.name]) {
            // property.value = parseModules(defmap[value.name], lineOfFile);
          }
        } else {
          // parseState(value, m2pmap, defmap);
        }
        // parseModules(property.value, m2pmap, defmap);
        break;
      default:
    }
  });
  return infoObj;
}

function parseState(objAst, lileOfFile) {
  let stateInfoList = [];
  objAst.properties.forEach(property => {
    let loc = property.loc;
    stateInfoList.push({
      rowKey: property.key.name,
      defination: lileOfFile.slice(loc.start.line - 1, loc.end.line).join('\n'),
    });
  });
  return stateInfoList;
}

function parseActions(objAst, m2pmap, defmap) {}

function parseGetters(objAst, m2pmap, defmap) {}
function parseMutations(objAst, m2pmap, defmap) {}
function parseModules({ objAst, m2pmap, defmap, cwf, lineOfFile }) {
  let infoObj = {};
  objAst.properties.forEach(property => {
    infoObj[property.key.name] = parseModuleAst(
      {
        objAst: property.value,
        m2pmap,
        defmap,
        cwf,
        lineOfFile,
      },
      infoObj,
    );
  });
  return infoObj;
}

function walkFile(base, relative = '') {
  let filename = getAbsolutePath(base, relative);
  let fileContent = getFileContent(filename);
  let ast = getAst(fileContent);
  let defineAstMap = getFileDefinationAstMap(ast);
  let moduleOrPathMap = getModuleOrPathMap(ast);
  let exportDefault = ast.program.body.filter(
    item => item.type === 'ExportDefaultDeclaration',
  )[0];
  return {
    export: exportDefault.declaration,
    lineOfFile: fileContent.split('\n'),
  };
}
function walkModulesFile(base, relative = '') {
  let filename = getAbsolutePath(base, relative);
  let fileContent = getFileContent(filename);
  let ast = getAst(fileContent);
  let defineAstMap = getFileDefinationAstMap(ast);
  let moduleOrPathMap = getModuleOrPathMap(ast);

  let exportDefault = ast.program.body.filter(
    item => item.type === 'ExportDefaultDeclaration',
  )[0];
  return {
    objAst: exportDefault.declaration,
    lineOfFile: fileContent.split('\n'),
    defmap: defineAstMap,
    m2pmap: moduleOrPathMap,
    cwf: filename,
  };
}
entryWalk();
